01Overview · Table Groups
15 tables grouped into 5 domains
📌
Scope: Tables derived from Subscribe screen (6-step wizard) · covers T&C consent · package/subscription · company (organization) · users + roles + permissions · payment flow (Omise + SlipOK + Bank) · invoice · tambon master.
| Group | Tables | Purpose |
|---|---|---|
| Auth & Consent | terms_versions, terms_articles, pdpa_versions, pdpa_consents | Store T&C + PDPA versions + user acceptance log |
| Package | packages, features, package_features | 4 subscription tiers + 9 features with M-M mapping |
| Organization | organizations, subscriptions | Company profile + active subscription details |
| Users & RBAC | users, roles, user_roles, role_permissions | Users invited from Step 04 + role assignment + module-level permission matrix |
| Payment | payments, payment_slips, invoices, tambon_master | Payment transactions (3 methods) + slip verification + invoice + address autocomplete |
02ER Diagram · Visual Overview
Boxes = tables · Lines = FK relationships · Grouped by color = domain
Figure 1 · Subscribe Web ER Diagram · 15 tables · 5 domain groups · data flows top-down through 6 wizard steps
03Sample Data (from ConstructQ_Subscribe.html)
Extracted directly from window.SUB_PACKAGES · window.SUB_FEATURES · window.SUB_ROLES · window.SUB_BANK
💎 packages (4 rows)
| id | code | name | price_monthly | price_yearly | user_quota | project_quota | is_popular |
|---|---|---|---|---|---|---|---|
1 | trial | Trial | 0 | 0 | 3 | 1 | false |
2 | starter | Starter | 3,900 | 42,900 | 10 | 3 | false |
3 | pro | Professional | 7,900 | 86,900 | 30 | 15 | true |
4 | enterprise | Enterprise | NULL (contact) | NULL | 9999 | 9999 | false |
🧩 features (9 rows · F1-F9)
| id | code | phase | name_en | name_th |
|---|---|---|---|---|
| 1 | F1 | 1 | Project & Zone Setup | Project & Zone Setup |
| 2 | F2 | 1 | Drawing & Doc Mgmt | Drawing & Doc Mgmt |
| 3 | F3 | 2 | Checklist Builder | Checklist Builder |
| 4 | F4 | 2 | Inspection Schedule | Inspection Schedule |
| 5 | F5 | 3 | Mobile Field Inspection | Mobile Field Inspection |
| 6 | F6 | 3 | NCR Management | NCR Management |
| 7 | F7 | 3 | Photo & Evidence Mgmt | Photo & Evidence Mgmt |
| 8 | F8 | 4 | Auto Report Generation | Auto Report Generation |
| 9 | F9 | 4 | Quality Dashboard | Quality Dashboard |
👥 roles (6 rows)
| id | code | name_th | name_en | description_en |
|---|---|---|---|---|
| 1 | org_admin | ผู้ดูแลระบบบริษัทฯ | Organize Admin | Organization administrator, manages users and org settings |
| 2 | pm | ผู้จัดการโครงการ | Project Manager | Manages projects, oversees resources and reporting |
| 3 | qc_mgr | ผู้จัดการตรวจสอบคุณภาพงาน | QC Manager | QC head, approves ITP plans and NCRs |
| 4 | qc_insp | ผู้ตรวจสอบคุณภาพงาน | QC (Inspector) | Field inspector, fills checklists and raises NCRs |
| 5 | sub | ผู้รับเหมา / ผู้รับเหมาช่วง | OP/Sub Contractor | Sub-contractor/foreman, handles NCR rework |
| 6 | ceo | ผู้บริหาร | CEO | Executive, views overall dashboard |
🏦 Bank Info (const · displayed in Step 05 Bank Transfer)
| Field | Value |
|---|---|
| bank_name | ธนาคารกสิกรไทย / Kasikorn Bank |
| bank_branch | สำนักงานใหญ่ / Headquarters |
| account_name | บริษัท วันโซลูชั่น อีอาร์พี จำกัด / One Solution ERP Co., Ltd. |
| account_no | 027-3-89456-1 |
💡
Full sample data set: Includes 4 packages · 9 features · 44 package_features (mapping) · 6 roles · 144 role_permissions (24 modules × 6 roles) · 1 T&C version · 11 T&C articles · 1 PDPA version · 1 sample organization + 3 sample users · 1 sample subscription + payment + invoice · 500+ tambon rows (Thai postal master). See seed script:
seed_subscribe_v3.0.py04APIs Mapped to Tables
11 endpoints · Go-Chi v5 handlers · tables touched per endpoint
| # | Endpoint | Handler Code | Method | Tables Touched | Purpose |
|---|---|---|---|---|---|
| 1 | /api/terms/latest | subscribe.GetLatestTerms | GET | terms_versions · terms_articles | Fetch latest T&C + all articles (Step 01) |
| 2 | /api/pdpa/latest | subscribe.GetLatestPDPA | GET | pdpa_versions | Fetch latest PDPA policy body |
| 3 | /api/consents/accept | subscribe.PostConsent | POST | pdpa_consents | Insert consent row after T&C + PDPA checkbox tick |
| 4 | /api/packages | subscribe.ListPackages | GET | packages · package_features · features | List all 4 packages with features (Step 02) |
| 5 | /api/tambon?q= | subscribe.SearchTambon | GET | tambon_master | Autocomplete search for Step 03 address |
| 6 | /api/uploads/logo | subscribe.UploadLogo | POST (multipart) | files (S3) · organizations.logo_url updated | Company logo upload (Step 03) |
| 7 | /api/roles | subscribe.ListRoles | GET | roles · role_permissions | List 6 roles + permission matrix (Step 04) |
| 8 | /api/subscriptions/register | subscribe.RegisterSubscription | POST (tx) | organizations · users · user_roles · subscriptions | Atomic multi-insert: org + users + subscription (Step 05 pre-payment) |
| 9 | /api/payments/omise/charge | subscribe.OmiseCharge | POST | payments (Omise integration) | Credit card charge via Omise API |
| 10 | /api/payments/slipok/verify | subscribe.SlipOKVerify | POST (multipart) | payment_slips · payments | Upload slip + SlipOK verify (PromptPay or Bank) |
| 11 | /api/users/invite-batch | subscribe.InviteUsersBatch | POST | users · notifications (email queue) | Send invitation emails after payment (Step 06) |
🔐 Error Codes (bilingual TH+EN)
| Code | HTTP | TH Message | EN Message |
|---|---|---|---|
SUB_001 | 400 | เลขประจำตัวผู้เสียภาษีต้อง 13 หลัก | Tax ID must be 13 digits |
SUB_002 | 400 | รูปแบบอีเมลไม่ถูกต้อง | Invalid email format |
SUB_003 | 409 | อีเมลนี้ถูกใช้แล้ว | Email already exists |
SUB_004 | 422 | รหัสผ่านต้องมีอย่างน้อย 8 ตัวอักษร | Password must be at least 8 characters |
SUB_005 | 402 | บัตรถูกปฏิเสธ | Card was declined |
SUB_006 | 422 | ยอดโอนไม่ตรงกับใบเสร็จ | Transfer amount does not match invoice |
SUB_007 | 413 | ไฟล์ใหญ่เกิน 5 MB | File size exceeds 5 MB |
SUB_008 | 415 | รองรับเฉพาะ PNG/JPG/SVG | Only PNG/JPG/SVG supported |
SUB_009 | 422 | จำนวนผู้ใช้งานเกินโควตาแพ็คเก็จ | User count exceeds package quota |
SUB_010 | 400 | ต้องยอมรับข้อกำหนดและ PDPA ก่อน | Must accept both T&C and PDPA |
05Table Details · Field-by-field
All 15 tables with columns, types, keys
📜
terms_versions
Auth & ConsentMaster versions of Terms & Conditions · effective-date driven · immutable per version
| Column | Type | Key | Note |
|---|---|---|---|
| id | uuid | PK | Primary key |
| version_no | varchar(20) | UNIQUE | e.g. "1.0" |
| effective_at | timestamptz | When this version takes effect | |
| published_by | uuid | FK users | Admin who published |
| is_current | boolean | Only one row true at a time | |
| created_at | timestamptz |
📝
terms_articles
Auth & Consent11 articles per T&C version (นิยาม, การสมัคร, บริการ, ค่าธรรมเนียม, IP, PDPA, SLA, ความรับผิด, ยกเลิก, การเปลี่ยนแปลง, ข้อพิพาท)
| Column | Type | Key | Note |
|---|---|---|---|
| id | uuid | PK | |
| version_id | uuid | FK terms_versions | |
| article_no | int | 1-11 | |
| title_th | text | ||
| title_en | text | ||
| body_th | text | JSON array of paragraphs | |
| body_en | text |
💎
packages
Package4 subscription tiers: Trial (free) · Starter · Professional (popular) · Enterprise (contact sales)
| Column | Type | Key | Note |
|---|---|---|---|
| id | uuid | PK | |
| code | varchar(20) | UNIQUE | trial | starter | pro | enterprise |
| name | varchar(100) | Display name | |
| eyebrow_th, eyebrow_en | varchar(50) | Small header | |
| subtitle_th, subtitle_en | text | ||
| price_monthly | numeric(12,2) | NULL for Enterprise | |
| price_yearly | numeric(12,2) | NULL for Enterprise | |
| yearly_savings | numeric(12,2) | ||
| user_quota | int | Max users | |
| project_quota | int | Max concurrent projects | |
| is_free | boolean | Trial=true | |
| is_popular | boolean | Show "Most Popular" badge | |
| is_contact | boolean | Enterprise=true | |
| bullets_th, bullets_en | jsonb | Array of feature bullets | |
| display_order | int | 1, 2, 3, 4 | |
| is_active | boolean |
🧩
features
Package9 core features F1-F9 · organized into 4 phases (Setup / Plan / Field / Report)
| Column | Type | Key | Note |
|---|---|---|---|
| id | uuid | PK | |
| code | varchar(10) | UNIQUE | F1..F9 |
| phase | int | 1-4 | |
| name_th, name_en | varchar(100) | ||
| desc_th, desc_en | text | ||
| is_active | boolean |
🔗
package_features
PackageMany-to-many junction · defines which features are included per package + quotas
| Column | Type | Key | Note |
|---|---|---|---|
| id | uuid | PK | |
| package_id | uuid | FK packages | |
| feature_id | uuid | FK features | |
| limit_value | int | e.g. AI Photo Analysis 200/mo | |
| limit_unit | varchar(20) | per_month · total · unlimited | |
| notes_th, notes_en | text |
🏢
organizations
OrganizationCompany profile from Step 03 · tax ID 13 digits · tambon-verified address
| Column | Type | Key | Note |
|---|---|---|---|
| id | uuid | PK | |
| name | varchar(200) | ชื่อบริษัท | |
| tax_id | varchar(13) | UNIQUE | 13-digit Thai tax |
| business_type | varchar(50) | construction · developer · consultant | |
| address_line1 | varchar(200) | ||
| address_line2 | varchar(200) | ||
| tambon | varchar(100) | ตำบล/แขวง | |
| district | varchar(100) | อำเภอ/เขต · from tambon lookup | |
| province | varchar(100) | จังหวัด · from tambon lookup | |
| postal_code | varchar(10) | from tambon lookup | |
| country | varchar(50) | Thailand default | |
| contact_name | varchar(100) | ||
| contact_phone | varchar(20) | ||
| contact_email | varchar(150) | ||
| logo_url | text | S3 path | |
| created_at, updated_at | timestamptz |
📋
subscriptions
OrganizationActive subscription · one row per organization at a time · handles Trial + paid
| Column | Type | Key | Note |
|---|---|---|---|
| id | uuid | PK | |
| org_id | uuid | FK organizations | |
| package_id | uuid | FK packages | |
| cycle | varchar(10) | monthly · yearly | |
| duration | int | Number of cycles | |
| start_date, end_date | date | ||
| status | varchar(20) | pending · active · expired · cancelled | |
| unit_price | numeric(12,2) | ||
| subtotal, vat_amount, total_price | numeric(12,2) | VAT 7% | |
| is_trial | boolean | ||
| trial_ends_at | timestamptz | Trial=30 days | |
| auto_renew | boolean |
👤
users
Users & RBACInvited users from Step 04 · sent invitation email · sets first password on first login
| Column | Type | Key | Note |
|---|---|---|---|
| id | uuid | PK | |
| org_id | uuid | FK organizations | |
| name | varchar(100) | ||
| varchar(150) | UNIQUE(org_id, email) | ||
| phone | varchar(20) | ||
| password_hash | varchar(255) | bcrypt · null until first login | |
| status | varchar(20) | pending · active · disabled | |
| invite_token | varchar(64) | 1-time use · 7-day expiry | |
| invited_at, first_login_at | timestamptz | ||
| avatar_url | text | ||
| locale | varchar(10) | th_TH · en_US |
💳
payments
PaymentPayment transactions · 3 methods: card (Omise), qr (PromptPay+SlipOK), bank (transfer+SlipOK)
| Column | Type | Key | Note |
|---|---|---|---|
| id | uuid | PK | |
| subscription_id | uuid | FK subscriptions | |
| org_id | uuid | FK organizations | Denorm for query speed |
| method | varchar(10) | card · qr · bank | |
| amount, vat_amount, total_amount | numeric(12,2) | ||
| status | varchar(20) | pending · paid · failed · refunded | |
| omise_charge_id | varchar(100) | chrg_test_xxx | |
| card_last4 | varchar(4) | ||
| card_brand | varchar(20) | visa · mastercard · jcb | |
| failure_reason | text | ||
| paid_at | timestamptz |
📄
invoices
PaymentTax invoice per successful payment · numbering per Thai Revenue Code §86
| Column | Type | Key | Note |
|---|---|---|---|
| id | uuid | PK | |
| payment_id | uuid | FK payments · UNIQUE | 1:1 |
| invoice_no | varchar(50) | UNIQUE | INV-2026-000001 |
| tax_invoice_no | varchar(50) | UNIQUE | TAX-2026-000001 |
| pdf_url | text | S3 path | |
| issued_at, sent_at | timestamptz |
🗺️
tambon_master
Payment / MasterThai postal master · seed with 77 provinces · ~7,500 tambon · used by Step 03 autocomplete
| Column | Type | Key | Note |
|---|---|---|---|
| id | serial | PK | |
| tambon_code | varchar(10) | UNIQUE | Government tambon code |
| tambon_th, tambon_en | varchar(100) | ||
| district_th, district_en | varchar(100) | ||
| province_th, province_en | varchar(100) | ||
| postal_code | varchar(10) |
📌
Remaining tables:
pdpa_versions · pdpa_consents · roles · user_roles · role_permissions · payment_slips — full schemas in the Excel companion (ConstructQ_Subscribe_Tables_v3.0.xlsx)06Seed Script Overview
seed_subscribe_v3.0.py · subscribe_seed_v3.0.sql
🐍
Sample data seed: Python script imports ALL data extracted from ConstructQ_Subscribe.html:
- packages (4) — Trial · Starter · Professional · Enterprise · exact prices + quotas + bullets
- features (9) — F1-F9 with phases 1-4 · TH + EN names + descriptions
- package_features (30+ rows) — Feature availability per package
- roles (6) — org_admin · pm · qc_mgr · qc_insp · sub · ceo
- role_permissions (144 rows) — 24 modules × 6 roles matrix from window.UM_PERMISSIONS
- terms_versions + terms_articles (11) — 1 v1.0 T&C + 11 articles TH/EN
- pdpa_versions (1) — v1.0 PDPA
- tambon_master (~50 popular tambon) — Bangkok districts as starter set (full 7,500 available via separate script)
- Sample organization + 3 users + 1 subscription (Trial) — For dev testing
▶️ Run the Seed
- Prerequisites: PostgreSQL 15+ · schema migrated ·
psycopg2orasyncpginstalled - Set env:
DATABASE_URL=postgresql://user:pass@localhost:5432/constructq - Run:
python seed_subscribe_v3.0.py - Or execute SQL directly:
psql $DATABASE_URL < subscribe_seed_v3.0.sql - Verify:
SELECT COUNT(*) FROM packages;should return 4
📁 Files Delivered
ConstructQ_Subscribe_ER_v3.0.html— this file · ER diagram + table catalogConstructQ_Subscribe_Tables_v3.0.xlsx— 4 sheets: Tables · Fields · Sample Data · APIsseed_subscribe_v3.0.py— Python seed script · idempotent · ON CONFLICT DO NOTHINGsubscribe_seed_v3.0.sql— Pure SQL alternativesubscribe_sample_data_v3.0.json— Raw JSON extracted from window.SUB_* variables